import re
import sys
import operator
import string

COMMENT_STRING = "#"

# width - size of each line of memory
# depth - number of lines in memory
# data - dictionary of line number to data
def generate_mif(width,depth,data):
    mif = ""
    header = "WIDTH = %d;\nDEPTH = %d;\nADDRESS_RADIX = DEC;\nDATA_RADIX = HEX;\nCONTENT BEGIN;\n"%(width,depth)
    mif += header
    for line in sorted(data.iterkeys()):
        mif += "%d : %X ;\n" % (line,data[line]%(1<<width))
    mif += "END;\n"
    return mif

if(len(sys.argv)<2):
    raise Exception("this script takes 1 input argument, the test case filename")
    
test_case = None
try:
    test_case = open(sys.argv[1]).read()
except:
    raise Exception("could not read specified test case")

table = {} # mock table, mapping of MAC to port
ages = {}
tc_data = {}
output_data = {}
t = 0
for line in test_case.split("\n"):
    line = line.split(COMMENT_STRING)[0].strip()
    if not line: continue
    input_data = line.split()
    if len(input_data) != 3: raise Exception("give <source MAC in hex> <source port in decimal> <dest MAC in hex>")
    source_addr = int(input_data[0],16) % (1 << 48)
    source_port = int(input_data[1]) % 4
    dest_addr = int(input_data[2],16) % (1 << 48)
    tc_data[t] = (source_addr << 50) | (source_port << 48) | dest_addr
    
    
    incr = 1
    if dest_addr in table:
        output_data[t] = table[dest_addr]
        incr = 2
        ages[dest_addr] = -1
    else:
        output_data[t] = 0b111 
        
    if dest_addr == source_addr:
    	output_data[t] = 0b1000

    if source_addr in table:
        del table[source_addr]
    elif len(table) == 32:
        # remove oldest item
        oldest_addr = max(ages.iteritems(),key=operator.itemgetter(1))[0]
        del table[oldest_addr]
        del ages[oldest_addr]
    table[source_addr] = source_port
		
    for addr in ages:
       ages[addr] += incr
       
    ages[source_addr] = 0

    t = t+1

tc_data[t] = 1 << 127

tc_mif = generate_mif(128, 1024, tc_data)
tc_f = open('input.mif','w')
tc_f.write(tc_mif)
tc_f.close()

output_mif = generate_mif(4, 1024, output_data)
out_f = open('output.mif','w')
out_f.write(output_mif)
out_f.close()